
#include <vector_types.h>
#include <math_functions.h>

#define ABS(a)		(((a) < 0) ? -(a) : (a))

struct Particula {
    float3 velocidade;
    float massaEspecifica;
    float pressao;
    float3 forcaPressao;
    float3 forcaVisc;
    float3 forcaAceleracao;
};

__global__ void PosicaoKernel(float3* posicoesParticulasT, float3* posicoesParticulasT2, Particula* particulasT2, int numeroParticulas, float passoIntegracao, unsigned int* values, float XminGrid, float XmaxGrid, float YminGrid, float YmaxGrid) {
    int thread = threadIdx.x;
    int block = blockIdx.x;
    int dim = blockDim.x;
    int indiceValue = dim * block + thread;

    if (indiceValue < numeroParticulas) {
        int indiceParticulaAtual = values[indiceValue];

        posicoesParticulasT2[indiceParticulaAtual].x = posicoesParticulasT[indiceParticulaAtual].x + passoIntegracao / 2 * particulasT2[indiceParticulaAtual].velocidade.x;
        posicoesParticulasT2[indiceParticulaAtual].y = posicoesParticulasT[indiceParticulaAtual].y + passoIntegracao / 2 * particulasT2[indiceParticulaAtual].velocidade.y;
        posicoesParticulasT2[indiceParticulaAtual].z = 0;

        if (posicoesParticulasT2[indiceParticulaAtual].x < XminGrid) {
            posicoesParticulasT2[indiceParticulaAtual].x = XminGrid + ABS(posicoesParticulasT2[indiceParticulaAtual].x - XminGrid);
        }
        if (posicoesParticulasT2[indiceParticulaAtual].x > XmaxGrid) {
            posicoesParticulasT2[indiceParticulaAtual].x = XmaxGrid - ABS(posicoesParticulasT2[indiceParticulaAtual].x - XmaxGrid);
        }
        if (posicoesParticulasT2[indiceParticulaAtual].y < YminGrid) {
            posicoesParticulasT2[indiceParticulaAtual].y = YminGrid + ABS(posicoesParticulasT2[indiceParticulaAtual].y - YminGrid);
        }
        if (posicoesParticulasT2[indiceParticulaAtual].y > YmaxGrid) {
            posicoesParticulasT2[indiceParticulaAtual].y = YmaxGrid - ABS(posicoesParticulasT2[indiceParticulaAtual].y - YmaxGrid);
        }
    }
}

extern "C" void launch_PosicaoKernel(unsigned int blocksPerGrid, unsigned int threadsPerBlock, float3* posicoesParticulasT, float3* posicoesParticulasT2, Particula* particulasT2, int numeroParticulas, float passoIntegracao, unsigned int* values,  float XminGrid, float XmaxGrid, float YminGrid, float YmaxGrid) {
    // execute the kernel
    PosicaoKernel<< <blocksPerGrid, threadsPerBlock >> >(posicoesParticulasT, posicoesParticulasT2, particulasT2, numeroParticulas, passoIntegracao, values,  XminGrid, XmaxGrid, YminGrid, YmaxGrid);
}



